import { cloneDeep } from "lodash-es";
import treeContextMenuConfig from "./treeContextMenuConfig.json";
// import typeNameConfig from './TypeNameConfig.json';
import menuItemPool from "./menuItemPool";
import { MenuItemPoolItem, SiderBarItem } from "./types";
import { markRaw } from "vue";
import { GraphNode } from "@/mdesign-lib/mdesign-app.umd.js";
import { modelUtil } from "@/mdesign-lib/mdesign-app.umd.js";
import siderbarConfig from "./siderbarConfig";
import { archService } from "@/mdesign-lib/mdesign-app.umd.js";
import { MetaclassType, NameSpaceMetaclass } from "@/mdesign-lib/mdesign-app.umd.js";
import { ProjectType, SharedStatus, UsedStatus } from "@/mdesign-lib/mdesign-app.umd.js";
import { StType } from "@/mdesign-lib/mdesign-app.umd.js";
import { modelService } from "@/mdesign-lib/mdesign-app.umd.js";
import { locale } from "@/mdesign-lib/mdesign-app.umd.js";
import { ActionKey } from "@/mdesign-lib/mdesign-app.umd.js";
import { relationIds, filterMeteTypeList } from "@/mdesign-lib/mdesign-app.umd.js";

export class ConfigManager {
  readonly treeContextMenuConfig: Record<string, string[]> = cloneDeep(treeContextMenuConfig);
  readonly menuItemPool: Record<string, MenuItemPoolItem> = cloneDeep(menuItemPool);
  readonly siderbarConfig: Record<string, { key: string; children: string[] }[]> = cloneDeep(siderbarConfig);
  readonly siderbarItems: Record<string, SiderBarItem> = {};

  readonly ignoreRefactorKeyList = new Set([
    StType["Customization::FlightDiagram"],
    StType["Customization::CommandAction"],
    StType["Customization::CommandInterval"],
    StType["Customization::TimeLine"],
    StType["Customization::GetElements"],
    StType["Customization::Qualification"],
    StType["Customization::GetProperties"],
    StType["Customization::ElementFilter"],
    StType["Customization::DiagramFilter"],
    StType["Customization::GetElementInfo"],
    StType["Customization::GetTables"],
    StType["Customization::GetSubPackages"],
    StType["Customization::GetSubDiagrams"],
    StType["Customization::GetDiagramElements"],
    StType["Customization::ElementInstanceFilter"],
    StType["Customization::StereotypeFilter"],
    StType["Customization::MetaClassFilter"],
    StType["Customization::NameFilter"],
    StType["Customization::DiagramInstanceFilter"],
    StType["Customization::DiagramTypeFilter"],
    StType["Customization::OwnerFilter"],
    StType["Customization::GetGeneralizeElements"],
    StType["Customization::GetDiagramImage"],
    StType["Customization::DocumentTemplateDiagram"]
  ]);
  constructor(public projectId: string) {
    markRaw(this);
  }
  async getNodeContextMenu(graphNode: GraphNode) {
    let menuKeys: string[];
    const selectedNodeIds = app.activeProject!.nodePool.selectedNodeIds;
    if (selectedNodeIds.length > 1) {
      menuKeys = [...this.treeContextMenuConfig["batchContextMenu"]];
    } else {
      const modelKey = modelUtil.getModelKey(graphNode.data);
      const metaclass = graphNode.data.metaclass || "";
      if (!modelKey) return [];
      menuKeys = [...(this.treeContextMenuConfig[modelKey] || [])];

      const defaultTreeContextMenuConfig = [
        "openCreateElement",
        "openCreateDiagram",
        "openCreateRelation",
        "showAttribute",
        "setNodeInEdit",
        "copyNode",
        "cutNode",
        "pasteNode",
        "showStereotype",
        "removeModel",
        "navTo"
      ];

      menuKeys = [...(this.treeContextMenuConfig[modelKey] || this.treeContextMenuConfig[metaclass] || defaultTreeContextMenuConfig)];

      // 映射模板，单独处理
      if (modelKey === StType["Customization::ReqIfMapToAttributes"] || modelKey === StType["Customization::ReqIfMapToRelations"]) {
        return Promise.all(menuKeys.map(it => cloneDeep(this.menuItemPool[it]) as MenuItemPoolItem));
      }
    }
    const structureCheckAvailable = await modelService.structureCheckAvailable({
      projectId: app.activeProject!.id,
      instanceId: graphNode.id
    });
    // 查询block所有的子构造型
    const childStModels = await modelService.getChildStereotypeModels(app.activeProject!.config.id, "SysML::Blocks::Block");
    const isBlock = childStModels.length && childStModels.find(child => child.id === graphNode.data.baseSt);
    const canCreateInstance = await modelService.canCreateInstance(this.projectId, graphNode.id);
    const isModelOrProfile = [MetaclassType.Model, MetaclassType.Profile, MetaclassType.Package].includes(
      graphNode?.data?.metaclass as MetaclassType
    );

    if (canCreateInstance || isBlock) {
      if (!menuKeys.includes("tool")) {
        menuKeys.push("tool");
      }
    }
    if (isModelOrProfile || structureCheckAvailable) {
      if (!menuKeys.includes("util")) {
        menuKeys.push("util");
      }
    }

    const autoNumers = await modelService.queryAutoNumbers({ projectId: app.activeProject!.id, instanceId: graphNode.data.id });
    if (autoNumers.length) menuKeys.push("manageNumber");

    if (selectedNodeIds.length <= 1 && !this.ignoreRefactorKeyList.has(graphNode.data.baseSt as StType)) {
      if (!menuKeys.includes("showStereotype")) {
        menuKeys.push("showStereotype");
      }
      menuKeys.push("refactor");
      if (
        !app.activeProject?.config.online &&
        app.activeProject?.config.type === ProjectType.MODEL &&
        graphNode.data?.sharedStatus === SharedStatus.STATUS_NO_SHARED
      ) {
        if (
          graphNode.data.metaclass &&
          !graphNode.data?.hiddenStatus &&
          (graphNode.data.metaclass === MetaclassType.Class ||
            graphNode.data.metaclass === MetaclassType.Package ||
            graphNode.data.metaclass === MetaclassType.Profile)
        ) {
          if (graphNode.data.isEncrypted) {
            menuKeys.push("decryptModel");
          } else {
            menuKeys.push("encryptModel");
          }
        }
      }
    }
    /**
     * 查询是否存在部件属性
     */
    if (graphNode?.data?.baseSt === StType["SysML::Blocks::Block"]) {
      menuKeys.push("securityAndReliability");
    }

    // Customization::GetElements  Customization::GetTables  Customization::DocumentTemplateDiagram

    if (graphNode?.data?.metaclass) {
      console.log(
        "graphNode?.data?.baseS",
        graphNode?.data,
        relationIds.has(graphNode?.data?.metaclass),
        filterMeteTypeList.includes(graphNode?.data?.metaclass)
      );

      if (relationIds.has(graphNode?.data?.metaclass) || filterMeteTypeList.includes(graphNode?.data?.metaclass)) {
        menuKeys.remove("refactor");
      } else {
        if (!menuKeys.includes("refactor")) {
          menuKeys.push("refactor");
        }
      }
    }

    // 特殊处理，活动图像需要展示入口
    const FilterStTypeList = [
      StType["Simulation::ActiveImage"], // 活动图像
      StType["SysML::Requirements::TestCase"] // 测试用例
    ];
    if (graphNode?.data?.baseSt && FilterStTypeList.includes(graphNode?.data?.baseSt)) {
      if (!menuKeys.includes("refactor")) {
        menuKeys.push("refactor");
      }
    }
    // 特殊处理，不需要展示入口
    // const notFilterStTypeList = [
    //   StType['Customization::LegendItem'], // 图例项
    // ];
    // if (graphNode?.data?.baseSt && notFilterStTypeList.includes(graphNode?.data?.baseSt)) {
    //   menuKeys.remove('refactor');
    // }

    // 模型合并入口
    const checkModelMergeType = await modelService.modelMergeCheckType({
      projectId: app.activeProject!.id,
      instanceId: graphNode.id,
      typeId: "Class"
    });
    // 模型库复用入口
    const checkModelLibTypes = await modelService.modelCheckTypes({
      projectId: app.activeProject!.id,
      instanceId: graphNode.id,
      typeIds: ["SysML::Requirements::Requirement", "SysML::Blocks::Block", "Behavior"]
    });
    if (checkModelMergeType || checkModelLibTypes) {
      if (!menuKeys.includes("refactor")) {
        menuKeys.push("refactor");
      }
    }

    // const check

    menuKeys = menuKeys.distinct();

    const contextMenus = menuKeys.map(async it => {
      const menuItem = cloneDeep(this.menuItemPool[it]) as MenuItemPoolItem;
      // console.log('menuItem', menuItem);
      if (!menuItem) return;
      // 判断是否有部件属性
      if (it === "securityAndReliability") {
        const hasPartProperty = await modelService.judgeHasPartProperty(graphNode.data.projectId, graphNode.data.id);
        if (!hasPartProperty) {
          menuItem.children = menuItem.children?.filter(child => {
            return child.value !== "reliabilityDistribute";
          });
        }
      } else if (menuItem.value === "refactor") {
        if (graphNode.data.metaclass) {
          // 判断是否需要添加替换菜单项
          // const shouldAddReplaceMenu = (
          //   (!relationIds.has(graphNode?.data?.metaclass) || !filterMeteTypeList.includes(graphNode?.data?.metaclass)) &&
          //   !filterReplaceIds.has(graphNode?.data?.metaclass) &&
          //   !filterReplaceNames.has(graphNode?.data?.name) &&
          //   graphNode?.data?.baseSt !== 'Customization::LegendItem'
          // );
          const shouldAddReplaceMenu = modelUtil.shouldAddReplaceMenu(graphNode.data.metaclass, graphNode.data.baseSt);
          if (!shouldAddReplaceMenu) {
            menuItem.children?.removeBy(i => i.value === "replaceTip");
            // menuItem.children?.push({
            //   label: "替换为",
            //   value: "replaceTip"
            // });
          }

          // 特殊处理，活动图像需要展示入口
          // if (graphNode?.data?.baseSt === StType['Simulation::ActiveImage']) {
          //   const hasThisItem = menuItem.children?.some((menu) => menu.value === 'replaceTip');
          //   // menuItem.children?.push({
          //   //   "label": "替换为",
          //   //   "value": "replaceTip"
          //   // });
          //   if (!hasThisItem) {
          //     menuItem.children.push({
          //       label: '替换为',
          //       value: 'replaceTip',
          //       disabled: false
          //     });
          //   }
          // }

          if (checkModelMergeType) {
            menuItem.children?.push({
              label: "合并",
              value: "modelMerge",
              disabled: false
            });
          }

          // 未加载模型库时不显示该菜单
          if (modelUtil.hasLoadModelLib() && checkModelLibTypes) {
            menuItem.children?.push({
              label: "模型库复用",
              value: "ModelLibReuse",
              disabled: false
            });
          }

          // 处理重定义
          const redefineItem = menuItem.children?.find(child => child.value === ActionKey.redefine);
          if (redefineItem) {
            const validRedefined = await modelService.checkElementIsRedefined(app.activeProject!.id, graphNode.id);
            redefineItem.disabled = !validRedefined;
          }

          // 处理变更方向
          if (modelUtil.isAssociation(graphNode.data.metaclass)) {
            const { projectId, id } = graphNode.data;

            // 调用后端判断是否展示方向菜单
            const isShowChangeDirectionMenu = await modelService.canConvertRelationshipDirection({ projectId: projectId, instanceId: id });
            const itemFlowList = await modelService.queryCurrentRealizedItemFlow({ projectId: projectId, instanceId: id });
            const changeDirectionMenu = menuItem.children?.find(item => item.value === "changeDirection");
            if (isShowChangeDirectionMenu && !changeDirectionMenu) {
              menuItem.children = menuItem.children || [];
              menuItem.children?.push({
                label: "变更方向",
                value: "changeDirection"
              });
            }
            /**
             * 以下情况置灰变更方向菜单:
             * 1. source / target 有一端为置灰
             * 2. 模型为引用模型
             * 3. 模型为封装模型
             */
            if (isShowChangeDirectionMenu) {
              const {
                usedStatus,
                isEncrypted,
                showAttribute: { sourceId, targetId },
                metaclass,
                id: modelId
              } = graphNode.data;
              const sourceDisabled = !!sourceId && (await modelService.isModelDisabled(sourceId, projectId));
              const targetDisabled = !!targetId && (await modelService.isModelDisabled(targetId, projectId));
              const modelDisabled = !!modelId && (await modelService.isModelDisabled(modelId, projectId));
              const isDisabledChangeDirection = usedStatus === UsedStatus.STATUS_USED || isEncrypted || sourceDisabled || targetDisabled;
              menuItem.children?.forEach?.(child => {
                if (child.value === "changeDirection") {
                  // 项流锁定编辑即可变更方向，其他需要判断上面的全部情况
                  child.disabled = metaclass === MetaclassType.InformationFlow ? modelDisabled : isDisabledChangeDirection;
                }
              });
            }
            const length = itemFlowList?.length;
            if (length === 1) {
              menuItem.children?.push({
                label: "变更流方向",
                value: "changeItemFlow",
                itemFlowId: itemFlowList[0]?.itemFlowId
              });
            } else if (length > 1) {
              menuItem.children?.push({
                label: "变更流方向",
                value: "changeItemFlow",
                children: itemFlowList.map(item => {
                  return {
                    label: locale.t("flowItem", { sourceName: item.sourceName, targetName: item.targetName }),
                    value: "changeItemFlow",
                    itemFlowId: item.itemFlowId
                  };
                })
              });
            }
          }
        }
      } else if (menuItem.value === "tool") {
        if (childStModels.find(child => child.id === graphNode.data.baseSt)) {
          menuItem.children = menuItem.children?.filter(child => child.value !== "saveDefaultValue");
        }
        if (graphNode?.data?.metaclass === MetaclassType.InstanceSpecification) {
          menuItem.children = menuItem.children?.filter(child => child.value !== "createIbdOnBehavior");
        }
        if (canCreateInstance) {
          if (!(childStModels.length && childStModels.find(child => child.id === graphNode.data.baseSt))) {
            menuItem.children = [
              {
                label: "创建实例",
                value: "autoCreateInstance"
              }
            ];
          } else {
            menuItem.children?.push({
              label: "创建实例",
              value: "autoCreateInstance"
            });
          }
        }

        // 是nameSpace空间元素都有
        if (graphNode?.data?.metaclass && NameSpaceMetaclass.indexOf(graphNode?.data?.metaclass) > -1) {
          menuItem.children?.push({
            label: "术语归一化",
            value: "CreateTermAction"
          });
        }

        if (isBlock) {
          menuItem.children?.push({
            label: "参数归一化",
            value: "normalizeParameter"
          });
        }
      } else if (menuItem.value === "util") {
        if (structureCheckAvailable) {
          menuItem.children?.push({
            label: "快速应用包结构配置",
            value: "quickApplyPackageStructureConfig"
          });
        }
        if (graphNode?.data?.metaclass && NameSpaceMetaclass.indexOf(graphNode?.data?.metaclass) > -1) {
          menuItem.children?.push({
            label: "术语归一化",
            value: "CreateTermAction"
          });
        }
        if (isModelOrProfile) {
          menuItem.children?.push({
            label: "参数归一化",
            value: "normalizeParameter"
          });
        }
      }
      return menuItem;
    });
    return Promise.all(contextMenus);
    // return this.treeContextMenuConfig;
  }

  // getSiderbarItemTree(diagramSt:StType):SiderBarItem[] {
  //   const config1 = this.siderbarConfig[diagramSt];
  //   if (!config1) return [];
  //   return config1.map(item => {

  //     const diagramConfigItem = siderbarDiagramItems[item.key];
  //     const children = item.children.map(key => this.siderbarItems[key]).filter(Boolean).map(it => ({ ...it, uid: getUid() }));

  //     const groupMap = new Map<string, SiderBarItem>();

  //     const result:SiderBarItem[] = [];
  //     children.forEach(child => {
  //       if (child.group) {
  //         let groupItem = groupMap.get(child.group);
  //         if (!groupItem) {
  //           groupMap.set(child.group, child);
  //           child.children = [];
  //           child.children.push({ ...child, children: undefined });
  //           groupItem = child;
  //           groupMap.set(groupItem.group as string, groupItem);
  //           result.push(groupItem);
  //         } else {
  //           groupItem.children!.push(child);
  //         }

  //       } else {
  //         result.push(child);
  //       }
  //     });

  //     return {
  //       key: item.key,
  //       ...diagramConfigItem,
  //       children: result
  //     };
  //   });
  // }

  async getSiderBarItem(key: string) {
    if (!this.siderbarItems[key]) {
      const newSiderbarItem = await archService.getSiderBarItem(app.activeProject!.id, key);
      if (newSiderbarItem) {
        this.siderbarItems[key] = newSiderbarItem;
      } else {
        throw new Error(`${key}侧边栏配置缺失！`);
      }
    }
    return cloneDeep(this.siderbarItems[key]);
  }
}
